﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MetaSharp.Transformation.Patterns
{
    class ErrorUntilPattern : Pattern
    {
        private Pattern pattern;

        public ErrorUntilPattern(Pattern pattern)
            : base(PatternKind.ErrorUntil)
        {
            this.pattern = pattern;
        }

        public override PatternMatch Compile()
        {
            var p = pattern.Compile();
            return s => Target(s, p);
        }

        public static async Task<IMatch> Target(IScope scope, PatternMatch pattern)
        {
            var start = scope;
            var s = start;
            var match = await Transformation.Match.Fail(scope);
            var error = false;

            while (!s.Stream.IsEmpty)
            {
                var m = await pattern(s);
                if (m.Matched)
                {
                    match = m;
                    break;
                }

                s = s.SetStream(s.Stream.Next());
                error = true;
            }

            if (error)
            {
                var e = new Error(
                    new SourceSpan(scope.Stream, s.Stream),
                    ErrorSeverity.Error,
                    "Values unexpected.");

                match = match.AddErrors(e);
            }

            if (match.Matched)
            {
                return match;
            }
            else
            {
                var m = await Transformation.Match.Default(s);
                return m.AddErrors(match.Errors);
            }
        }
    }
}
